/*
 * Thread.cpp
 *
 *  Created on: 2009/12/14
 *      Author: Peter.Song
 */

#include <iostream>
#include "Thread.h"

using namespace std;

#ifdef WIN32 //win32 thread
__declspec( thread ) CLocalMempool* TH_LOCAL_MEMPOOL_PTR;

CXThread::CXThread()
: m_thread(NULL)
, m_target(NULL)
{

}

CXThread::CXThread(CRunnable* target)
: m_thread(NULL)
, m_target(target)
{

}

CXThread::~CXThread()
{
	CloseHandle(m_thread);
}

void CXThread::Initalize()
{
	// run in main thread
	TH_LOCAL_MEMPOOL_PTR = new CLocalMempool();
}

void CXThread::Finalize()
{
	// run in main thread
	delete TH_LOCAL_MEMPOOL_PTR;
}

void CXThread::Start()
{
	unsigned tid;
    m_thread = (HANDLE) _beginthreadex(NULL,0,thread_entry,this,0,&tid);
	if(m_thread == NULL){
		cout << "create thread failed!" << endl;
		return;
	}
}

THREAD_ENTRY_FUNC(CXThread::thread_entry)
{
	CXThread* pthis = static_cast<CXThread*>(param);
	pthis->run();
	_endthreadex(0);
	return 0;
}

void CXThread::Join()
{
	if(m_thread) {
		DWORD ret = WaitForSingleObject(m_thread, INFINITE);
		if(ret == 0xFFFFFFFF){
			cout << "thread join failed!" << endl;
		}
	}
}

#else //Posix thread

__thread CLocalMempool* TH_LOCAL_MEMPOOL_PTR = NULL;

CXThread::CXThread()
: m_thread(0)
, m_target(NULL)
{

}

CXThread::CXThread(CRunnable* target)
: m_thread(0)
, m_target(target)
{

}

CXThread::~CXThread()
{

}

void CXThread::Initalize()
{
	// run in main thread
	CLocalMempool* addr;
	addr = new CLocalMempool();
	TH_LOCAL_MEMPOOL_PTR = addr;
}

void CXThread::Start()
{
	int ret = -1;
	ret = pthread_create(&m_thread, NULL, thread_entry, this);
	if(ret){
		cout << "create thread failed!" << endl;
		return;
	}
}

THREAD_ENTRY_FUNC(CXThread::thread_entry)
{
	CXThread* pthis = static_cast<CXThread*>(param);
	pthis->run();
	return NULL;
}

void CXThread::Finalize()
{
	// run in main thread
	delete TH_LOCAL_MEMPOOL_PTR;
	TH_LOCAL_MEMPOOL_PTR = NULL;
}

void CXThread::Join()
{
	int ret = pthread_join(m_thread, NULL);
	if(ret){
		cout << "Doing join failed!" << endl;
	}
}

#endif

void CXThread::run()
{
	if(m_target){
		TH_LOCAL_MEMPOOL_PTR = new CLocalMempool();

		m_target->Run(); // Executing user-specified function

		delete TH_LOCAL_MEMPOOL_PTR;
		TH_LOCAL_MEMPOOL_PTR = NULL;
	}
}

void CXThread::SetRunnableTarget(CRunnable* target)
{
	m_target = target;
}
